﻿using CSharpSkin.ScrollBar.Constant;
using CSharpSkin.ScrollBar.Struct;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CSharpSkin.ScrollBar.Class
{
    #region 基础窗体抽象
    /// <summary>
    /// WWW.CSharpSkin.COM
    /// 基础窗体抽象
    /// </summary>
    public abstract class NativeWindowBase : NativeWindow, IDisposable
    {
        #region 成员
        private CreateParams _createParams;
        private bool _disposed;
        #endregion

        #region 构造
        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="hWnd"></param>
        protected NativeWindowBase(IntPtr hWnd): base()
        {
            this.CreateParamsWindow(hWnd);
        }

        protected NativeWindowBase(IntPtr hWnd, Rectangle rect)
        {
            this.CreateParamsWindow(hWnd, rect);
        }

        ~NativeWindowBase()
        {
            Dispose(false);
        }

        #endregion


        #region 获取窗口句柄是否已经创建
        /// <summary>
        /// 获取窗口句柄是否已经创建。
        /// </summary>
        protected bool IsHandleCreated
        {
            get { return base.Handle != IntPtr.Zero; }
        }
        #endregion

        protected virtual CreateParams CreateParams
        {
            get
            {
                return _createParams;
            }
        }

        #region 创建窗口的句柄
        /// <summary>
        /// 创建窗口的句柄。
        /// </summary>
        public void OnCreateHandle()
        {
            base.CreateHandle(CreateParams);
            SetZorder();
        }
        #endregion

        /// <summary>
        /// 重绘
        /// </summary>
        /// <param name="hWnd"></param>
        protected virtual void OnPaint(IntPtr hWnd)
        {
        }

        #region 监听系统消息并重绘
        /// <summary>
        /// 监听系统消息并重绘
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            try
            {
                switch (m.Msg)
                {
                    case WINDOWMESSAGE.WM_NCPAINT:
                    case WINDOWMESSAGE.WM_PAINT:
                        OnPaint(m.HWnd);
                        break;
                }
            }
            catch
            {
            }
        }
        #endregion

        #region 设置窗口参数
        /// <summary>
        /// 设置窗口参数
        /// </summary>
        /// <param name="hWnd"></param>
        public void CreateParamsWindow(IntPtr hWnd)
        {
            IntPtr hParent = CSharpWinapi.GetParent(hWnd);
            RECT rect = new RECT();
            Point point = new Point();
            CSharpWinapi.GetWindowRect(hWnd, ref rect);
            point.X = rect.Left;
            point.Y = rect.Top;
            CSharpWinapi.ScreenToClient(hParent, ref point);
            int dwStyle =SS.SS_OWNERDRAW |WS.WS_CHILD |WS.WS_CLIPSIBLINGS |WS.WS_OVERLAPPED | WS.WS_VISIBLE;
            int dwExStyle = WS_EX.WS_EX_TOPMOST | WS_EX.WS_EX_TOOLWINDOW;
            _createParams = new CreateParams();
            _createParams.Parent = hParent;
            _createParams.ClassName = CSharpWinapi.STATIC;
            _createParams.Caption = null;
            _createParams.Style = dwStyle;
            _createParams.ExStyle = dwExStyle;
            _createParams.X = point.X;
            _createParams.Y = point.Y;
            _createParams.Width = rect.Right - rect.Left;
            _createParams.Height = rect.Bottom - rect.Top;
        }
        #endregion

        #region 设置窗口参数
        /// <summary>
        /// 设置窗口参数
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="rect"></param>
        public void CreateParamsWindow(IntPtr hWnd, Rectangle rect)
        {
            IntPtr hParent = CSharpWinapi.GetParent(hWnd);
            int dwStyle =SS.SS_OWNERDRAW |WS.WS_CHILD |WS.WS_CLIPSIBLINGS |WS.WS_OVERLAPPED | WS.WS_VISIBLE;
            int dwExStyle = WS_EX.WS_EX_TOPMOST | WS_EX.WS_EX_TOOLWINDOW;
            _createParams = new CreateParams();
            _createParams.Parent = hParent;
            _createParams.ClassName = CSharpWinapi.STATIC;
            _createParams.Caption = null;
            _createParams.Style = dwStyle;
            _createParams.ExStyle = dwExStyle;
            _createParams.X = rect.X;
            _createParams.Y = rect.Y;
            _createParams.Width = rect.Width;
            _createParams.Height = rect.Height;
        }
        #endregion

        #region 销毁窗体句柄
        /// <summary>
        /// 销毁窗体句柄
        /// </summary>
        void DestroyWindowHandle()
        {
            if (IsHandleCreated)
            {
                base.DestroyHandle();
            }
        }
        #endregion

        #region 检查窗口区域并重新设置位置
        /// <summary>
        /// 检查窗口区域并重新设置位置
        /// </summary>
        /// <param name="hWnd"></param>
        public void CheckBounds(IntPtr hWnd)
        {
            RECT controlRect = new RECT();
            RECT maskRect = new RECT();
            CSharpWinapi.GetWindowRect(base.Handle, ref maskRect);
            CSharpWinapi.GetWindowRect(hWnd, ref controlRect);
            uint uFlag =WP.WP_NOACTIVATE |WP.WP_NOOWNERZORDER |WP.WP_NOZORDER;
            if (!CSharpWinapi.EqualRect(ref controlRect, ref maskRect))
            {
                Point point = new Point(controlRect.Left, controlRect.Top);
                IntPtr hParent = CSharpWinapi.GetParent(base.Handle);
                CSharpWinapi.ScreenToClient(hParent, ref point);
                CSharpWinapi.SetWindowPos( base.Handle,IntPtr.Zero,point.X,point.Y,controlRect.Right - controlRect.Left,controlRect.Bottom - controlRect.Top,uFlag);
            }
        }
        #endregion

        #region 显示或隐藏窗口
        /// <summary>
        /// 显示或隐藏窗口
        /// </summary>
        /// <param name="hWnd"></param>
        public void SetVisibale(IntPtr hWnd)
        {
            bool bVisible = (CSharpWinapi.GetWindowLong(hWnd,GWL.GWL_STYLE) & WS.WS_VISIBLE) == WS.WS_VISIBLE;
            SetVisibale(bVisible);
        }
        #endregion

        #region 显示或隐藏窗口
        /// <summary>
        /// 显示或隐藏窗口
        /// </summary>
        /// <param name="visibale"></param>
        public void SetVisibale(bool visibale)
        {
            if (visibale)
            {
                CSharpWinapi.ShowWindow(base.Handle, SW.SW_NORMAL);
            }
            else
            {
                CSharpWinapi.ShowWindow(base.Handle, SW.SW_HIDE);
            }
        }
        #endregion

        #region 设置窗口位置
        /// <summary>
        /// 设置窗口位置
        /// </summary>
        private void SetZorder()
        {
            uint uFlags =WP.WP_NOMOVE |WP.WP_NOSIZE | WP.WP_NOACTIVATE |WP.WP_NOOWNERZORDER;
            CSharpWinapi.SetWindowPos(base.Handle,HWND.HWND_TOP,0,0,0,0,uFlags);
        }
        #endregion

        #region 释放
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _createParams = null;
                }
                DestroyHandle();
            }
            _disposed = true;
        }
        #endregion
    }
    #endregion
}
